package com.xuzhiguang.lightnat.client;

import com.xuzhiguang.lightnat.client.control.ControlClient;
import com.xuzhiguang.lightnat.client.control.ControlClientHolder;
import com.xuzhiguang.lightnat.client.control.processor.ConnectPushProcessor;
import com.xuzhiguang.lightnat.client.control.processor.ControlAuthenticationResponseProcessor;
import com.xuzhiguang.lightnat.client.proxy.ProxyClient;
import com.xuzhiguang.lightnat.client.proxy.ProxyClientHolder;
import com.xuzhiguang.lightnat.client.transfer.*;
import com.xuzhiguang.lightnat.client.transfer.processor.DisconnectPushProcessor;
import com.xuzhiguang.lightnat.client.transfer.processor.TransferAuthenticationResponseProcessor;
import com.xuzhiguang.lightnat.client.transfer.processor.TransferPushProcessor;
import com.xuzhiguang.lightnat.common.message.MessageProcessorFactory;
import com.xuzhiguang.lightnat.common.message.NatMessageTypeEnum;

public class App {

    public static void main(String[] args) {

        ClientProperties clientProperties = new ClientProperties();

        MessageProcessorFactory controlMessageProcessorFactory = new MessageProcessorFactory.Builder()
                .addProcessor(NatMessageTypeEnum.CONNECT_PUSH.getType(), new ConnectPushProcessor())
                .addProcessor(NatMessageTypeEnum.CONTROL_AUTHENTICATION_RESPONSE.getType(), new ControlAuthenticationResponseProcessor())
                .build();
        ControlClient controlClient = new ControlClient(clientProperties, controlMessageProcessorFactory);
        ControlClientHolder.set(controlClient);
        controlClient.start();

        TransferClient transferClient = new TransferClient(clientProperties);
        TransferChannelPoolImpl transferChannelPool = new TransferChannelPoolImpl(transferClient, 10, 60000);
        TransferAuthenticationResponseProcessor transferAuthenticationResponseProcessor
                = new TransferAuthenticationResponseProcessor();
        TransferChannelPoolImpl.PoolTransferAuthenticationListener transferAuthenticationListener
                = new TransferChannelPoolImpl.PoolTransferAuthenticationListener(transferChannelPool);
        transferAuthenticationResponseProcessor.setTransferAuthenticationListener(transferAuthenticationListener);
        MessageProcessorFactory transferMessageProcessorFactory = new MessageProcessorFactory.Builder()
                .addProcessor(NatMessageTypeEnum.DISCONNECT_PUSH.getType(), new DisconnectPushProcessor())
                .addProcessor(NatMessageTypeEnum.TRANSFER_AUTHENTICATION_RESPONSE.getType(), transferAuthenticationResponseProcessor)
                .addProcessor(NatMessageTypeEnum.TRANSFER.getType(), new TransferPushProcessor())
                .build();

        transferClient.setMessageProcessorFactory(transferMessageProcessorFactory);
        TransferChannelPoolHolder.set(transferChannelPool);
        transferClient.start();

        ProxyClient proxyClient = new ProxyClient();
        ProxyClientHolder.set(proxyClient);
        proxyClient.start();

        System.out.println("lightnat client started...");

        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            proxyClient.stop();
            controlClient.stop();
            transferClient.stop();
        }));

    }


}
